home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / space / software / unix / xanim / xanim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-04  |  42.1 KB  |  1,557 lines

  1.  
  2. /*
  3.  * xanim.c
  4.  *
  5.  * Copyright (C) 1990,1991,1992 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed
  9.  * without fee provided that this copyright notice is preserved 
  10.  * intact on all copies and modified copies.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) all
  14.  * responsibility and liability with respect to this software's usage
  15.  * or its effect upon hardware or computer systems.
  16.  *
  17.  */
  18.  
  19. #define DA_REV 2.29
  20. #define DA_MINOR_REV 7
  21.  
  22. /*
  23.  * Any problems, suggestions, solutions, etc contact:
  24.  *
  25.  * podlipec@dgxyris.webo.dg.com
  26.  *
  27.  */
  28.  
  29. #include "xanim.h"
  30. #include "xanim_config.h"
  31. #include <X11/Intrinsic.h>
  32. #include <X11/StringDefs.h>
  33. #include <X11/Shell.h>
  34. #include <sys/signal.h>
  35. #include <sys/param.h>
  36. #include <sys/times.h>
  37. #include <ctype.h>
  38. #include "xanim_x11.h"
  39.  
  40. void TheEnd();
  41. void TheEnd1();
  42. void Usage();
  43. ULONG GetWord();
  44. ULONG GetHalfWord();
  45. void ShowAnimation();
  46. void ShowAction();
  47. int Determine_Anim_Type();
  48. void Cycle_It();
  49. void Step_File_Next();
  50. void Step_File_Prev();
  51. void Step_Frame_Next();
  52. void Step_Frame_Prev();
  53. void Step_Action_Next();
  54. void Free_Actions();
  55. ANIM_HDR *Get_Anim_Hdr();
  56.  
  57. /*
  58.  * Global X11 display configuation variables
  59.  *
  60.  * These are set by X11_Pre_Setup();
  61.  *
  62.  */
  63.  
  64. int x11_depth;
  65. int x11_class;
  66. int x11_bytes_pixel;
  67. int x11_bitmap_unit;
  68. int x11_bit_order;
  69. int x11_cmap_flag;
  70. int x11_cmap_size;
  71. int x11_display_type;
  72. int x11_red_mask;
  73. int x11_green_mask;
  74. int x11_blue_mask;
  75. int x11_red_shift;
  76. int x11_green_shift;
  77. int x11_blue_shift;
  78. int x11_red_size;
  79. int x11_green_size;
  80. int x11_blue_size;
  81. int x11_black;
  82. int x11_white;
  83. int x11_verbose_flag;
  84.  
  85. /*
  86.  * Each animation is broken up into a series of individual actions.
  87.  * For example, a gif image would become two actions, 1 to setup the
  88.  * colormap and 1 to display the image.
  89.  *
  90.  * ACTION is defined in xanim.h. 
  91.  *
  92.  * action_cnt is a global variable that points to the next unused action.
  93.  * Currently, individual routines access this. This will change.
  94.  *
  95.  * action_start is a variable passed to the Read_Animation routines, It
  96.  * keeps track of the 1st action available to routine.
  97.  *
  98.  */
  99. ACTION action[3000];
  100. int action_cnt;
  101. int action_start;
  102.  
  103. /*
  104.  * This structure is set up for each animation file. It keeps track of
  105.  * special flags and which animation type.
  106.  *
  107.  * anim_type is one of IFF_,FLI_,GIF_,TXT_,FADE_ANIM. 
  108.  *
  109.  * merged_anim_flags is the or of all anims read in. FLI's anims need
  110.  * only 1 buffer. IFF anims need two. This allows software to allocate
  111.  * for the worst case.
  112.  *
  113.  */
  114. ANIM_HDR anim;
  115. int anim_type;
  116. int merged_anim_flags;
  117.  
  118.  
  119. /*
  120.  * cmap keeps track of the current colors to the screen.
  121.  *
  122.  * hmap is IFF HAM specific and is needed to decode HAM images into 332
  123.  * and into 24bits when supported.
  124.  *
  125.  * image_map is used for encoded(any image not in the correct format) images.
  126.  * and is used to map image pixels to their correct color map entry.
  127.  * also used to map  mapped images to TRUE_COLOR.
  128.  *
  129.  */
  130. ColorReg *cmap = 0;
  131. ColorReg ham_map[HMAP_SIZE];
  132. ColorReg *image_map = 0;
  133. int cmap_luma_sort;
  134. int cmap_try_to_1st;
  135. int cmap_map_to_1st;
  136.  
  137. /*
  138.  * Global variable to keep track of Anim type
  139.  */
  140. int filetype;
  141.  
  142. /*
  143.  * Global variables to keep track of current width, height, num of colors and
  144.  * number of bit planes respectively. 
  145.  *
  146.  * the max_ variable are used for worst case allocation. Are useful for Anims
  147.  * that have multiple image sizes.
  148.  *
  149.  * image_size and max_image_size are imagex * imagey, etc.
  150.  */
  151. int imagex, imagey, max_imagex, max_imagey;
  152. int disp_y, max_disp_y;
  153. int imagec, imaged;
  154. int image_size;
  155. int max_image_size;
  156.  
  157. /* 
  158.  * These variable keep track of where we are in the animation.
  159.  * cur_file  ptr to the header of the current anim file. 
  160.  * cur_floop keeps track of how many times we've looped a file.
  161.  * cur_frame keeps track of which frame(action) we're on.
  162.  *
  163.  * cycle_wait and cycle_cnt are used for color cycling.
  164.  *
  165.  * file_is_started indicates whether this is the 1st time we've looped a file
  166.  * or not. Is used to initialize variables and resize window if necessary.
  167.  * 
  168.  */
  169. ANIM_HDR *cur_file   = 0;
  170. ANIM_HDR *first_file = 0;
  171. int cur_floop,cur_frame;
  172. int cycle_wait,cycle_cnt;
  173. int file_is_started;
  174. /*
  175.  * Image buffers.
  176.  * im_buff1 is used for double buffered anims(IFF).
  177.  * disp_buff is needed when the display is of a different format than the
  178.  * double buffered images. (like HAM or TRUE_COLOR).
  179.  *
  180.  * pic is a pointer to im_buff0 or im_buff1 during double buffering.
  181.  *
  182.  */
  183. char *im_buff0,*im_buff1,*pic,*disp_buff;
  184.  
  185. /* 
  186.  * Global flags that are set on command line.
  187.  */
  188. int buff_flag;
  189. int cycle_on_flag;
  190. int fade_flag,fade_time;
  191. int noresize_flag;
  192. int update_flag;
  193. int optimize_flag;
  194. int pixmap_flag;
  195. int dither_flag;
  196. int pack_flag;
  197. int debug;
  198. int verbose;
  199.  
  200. int loopeach_flag;
  201. int jiffy_flag;
  202.  
  203. int anim_flags;
  204. int anim_holdoff;
  205. int anim_status;
  206. int anm_map_flag;
  207.  
  208. /*
  209.  * old_dlta is used for optimizing screen updates for IFF and FLI animations.
  210.  *
  211.  * act is a global pointer to the current action.
  212.  *
  213.  */
  214. ACTION *act;
  215.  
  216. /*
  217.  * This function (hopefully) provides a clean exit from our code.
  218.  */
  219. void TheEnd()
  220. {
  221.   ANIM_HDR *tmp_hdr;
  222.  
  223.   Free_Actions();
  224.   cur_file = first_file;
  225.   first_file->prev_file->next_file = 0;  /* last file's next ptr to 0 */
  226.   while( cur_file != 0)
  227.   {
  228.     tmp_hdr = cur_file->next_file;
  229.     free(cur_file);
  230.     cur_file = tmp_hdr;
  231.   }
  232.   if (im_buff0) free(im_buff0);
  233.   if (im_buff1) free(im_buff1);
  234.   if (disp_buff) free(disp_buff);
  235.   if (cmap) free(cmap);
  236.   if (theDisp) XtCloseDisplay(theDisp);
  237.   exit(0);
  238. }
  239.  
  240. void Hard_Death()
  241. {
  242.   exit(0);
  243. }
  244.  
  245. /*
  246.  * just prints a message before calling TheEnd()
  247.  */
  248. void TheEnd1(err_mess)
  249. char *err_mess;
  250. {
  251.  fprintf(stderr,"%s\n",err_mess);
  252.  TheEnd();
  253. }
  254.  
  255. void
  256. Usage_Default_TF(flag,justify)
  257. ULONG flag,justify;
  258. {
  259.   if (justify == 1) fprintf(stderr,"            ");
  260.   if (flag == TRUE) fprintf(stderr," default is on.\n");
  261.   else fprintf(stderr," default is off.\n");
  262. }
  263.  
  264. void
  265. Usage_Default_Num(num,justify)
  266. ULONG num,justify;
  267. {
  268.   if (justify == 1) fprintf(stderr,"            ");
  269.   fprintf(stderr," default is %ld.\n",num);
  270. }
  271.  
  272. /*
  273.  * This function attempts to expain XAnim's usage if the command line
  274.  * wasn't correct.
  275.  */
  276. void Usage()
  277. {
  278.  fprintf(stderr,"Usage:\n\n");
  279.  fprintf(stderr,"xanim [ [+|-]opts ...] animfile [ [ [+|-opts] animfile] ... ]\n");
  280.  fprintf(stderr,"\n");
  281.  if (DEFAULT_PLUS_IS_ON == TRUE) 
  282.       fprintf(stderr,"A + turns an option on and a - turns it off.\n");
  283.  else fprintf(stderr,"A - turns an option on and a + turns it off.\n");
  284.  fprintf(stderr,"Options d,f,j and l ignore leading + and -'s.\n");
  285.  fprintf(stderr,"Leave a space after #'s\n");
  286.  fprintf(stderr,"\n");
  287.  fprintf(stderr,"Options:\n");
  288.  fprintf(stderr,"\n");
  289.  fprintf(stderr,"       Cl   luma sort colormaps.");
  290.  Usage_Default_TF(DEFAULT_CMAP_LUMA_SORT,0);
  291.  fprintf(stderr,"       Ct   try to fit new cmaps to 1st cmap.");
  292.  Usage_Default_TF(DEFAULT_CMAP_TRY_TO_1ST,0);
  293.  fprintf(stderr,"       Cf   force/map new cmaps to 1st cmap.");
  294.  Usage_Default_TF(DEFAULT_CMAP_MAP_TO_1ST,0);
  295.  fprintf(stderr,"       F    Floyd-Steinberg dithering when needed.\n");
  296.  Usage_Default_TF(DEFAULT_DITHER_FLAG,1);
  297.  fprintf(stderr,"       b    buffers images ahead of time."); 
  298.  Usage_Default_TF(DEFAULT_BUFF_FLAG,0);
  299.  fprintf(stderr,"       c    disable looping for nonlooping iff anims.\n"); 
  300.  Usage_Default_TF(DEFAULT_IFF_LOOP_OFF,1);
  301.  fprintf(stderr,"       d#   debug. 1 to 5 for level of report.\n"); 
  302.  Usage_Default_Num(DEFAULT_DEBUG,1);
  303.  fprintf(stderr,"       f#   fade to black in 16 frames. frame delay=#ms\n");
  304.  Usage_Default_TF(DEFAULT_FADE_FLAG,1);
  305.  fprintf(stderr,"       i    Interlace flag. Reduce image height by two\n"); 
  306.  Usage_Default_TF(FALSE,1);
  307.  fprintf(stderr,"       j#   # is number of milliseconds between frames\n");
  308.  fprintf(stderr,"         if 0 then default depends on the animation\n");
  309.  Usage_Default_Num(DEFAULT_JIFFY_FLAG,1);
  310.  fprintf(stderr,"       l#   # is number of times each file is shown\n");
  311.  fprintf(stderr,"             before moving on.\n");
  312.  Usage_Default_Num(DEFAULT_LOOPEACH_FLAG,1);
  313.  fprintf(stderr,"       o    turns on certain optimizations. See readme\n"); 
  314.  Usage_Default_TF(DEFAULT_OPTIMIZE_FLAG,1);
  315.  fprintf(stderr,"       p    Use Pixmap instead of Image in X11.\n"); 
  316.  Usage_Default_TF(DEFAULT_PIXMAP_FLAG,1);
  317.  fprintf(stderr,"       r    turn color cycling off. Currently only for\n");
  318.  fprintf(stderr,"            single images."); 
  319.  Usage_Default_TF(DEFAULT_CYCLE_ON_FLAG,0);
  320.  fprintf(stderr,"       s    prevents window from resizing to match image\n"); 
  321.  fprintf(stderr,"             size. Window is the size of largest image.\n"); 
  322.  Usage_Default_TF(DEFAULT_NORESIZE_FLAG,1);
  323.  fprintf(stderr,"       u    when single stepping, anim is played until\n");
  324.  fprintf(stderr,"             image is updated/changed.(a new cmap is\n");
  325.  fprintf(stderr,"             not considered an update).");
  326.  Usage_Default_TF(DEFAULT_UPDATE_FLAG,0);
  327.  fprintf(stderr,"       v    verbose mode."); 
  328.  Usage_Default_TF(DEFAULT_VERBOSE,0);
  329.  fprintf(stderr,"\n");
  330.  fprintf(stderr,"Window commands.\n");
  331.  fprintf(stderr,"\n");
  332.  fprintf(stderr,"        q    quit\n");
  333.  fprintf(stderr,"        g    For cycling images, move to next file\n");
  334.  fprintf(stderr,"        s    Stop cycling\n");
  335.  fprintf(stderr,"        r    Restore Colors after stopping cycling\n");
  336.  fprintf(stderr,"      space  toggle. starts/stops animation\n");
  337.  fprintf(stderr,"        ,    go back one frame within file\n");
  338.  fprintf(stderr,"        .    go forward one frame within file\n");
  339.  fprintf(stderr,"        <    go back to start of previous file\n");
  340.  fprintf(stderr,"        >    go forward to start of next file\n");
  341.  fprintf(stderr,"\n");
  342.  
  343.  exit(0);
  344. }
  345.  
  346. main(argc, argv)
  347. int argc;
  348. char *argv[];
  349. {
  350.  char *filename,*in;
  351.  int i,j;
  352.  
  353. /* 
  354.  * Initialize global variables.
  355.  */
  356.  theDisp = NULL;
  357.  
  358.  im_buff0 = 0;
  359.  im_buff1 = 0;
  360.  disp_buff = 0;
  361.  max_imagex = 0;
  362.  max_imagey = 0;
  363.  max_disp_y = 0;
  364.  image_map = cmap;
  365.  
  366.  first_file = cur_file = 0;
  367.  action_cnt = 0;
  368.  
  369.  anim_holdoff  = TRUE;
  370.  anim_status   = XA_UNSTARTED;
  371.  
  372.  buff_flag     = DEFAULT_BUFF_FLAG;
  373.  pack_flag     = DEFAULT_PACK_FLAG;
  374.  cycle_on_flag = DEFAULT_CYCLE_ON_FLAG;
  375.  noresize_flag = DEFAULT_NORESIZE_FLAG;
  376.  verbose       = DEFAULT_VERBOSE;
  377.  debug         = DEFAULT_DEBUG;
  378.  update_flag   = DEFAULT_UPDATE_FLAG;
  379.  optimize_flag = DEFAULT_OPTIMIZE_FLAG;
  380.  pixmap_flag   = DEFAULT_PIXMAP_FLAG;
  381.  dither_flag   = DEFAULT_DITHER_FLAG;
  382.  loopeach_flag = DEFAULT_LOOPEACH_FLAG;
  383.  jiffy_flag    = DEFAULT_JIFFY_FLAG;
  384.  x11_verbose_flag = DEFAULT_X11_VERBOSE_FLAG;
  385.  cmap_luma_sort   = DEFAULT_CMAP_LUMA_SORT;
  386.  cmap_try_to_1st  = DEFAULT_CMAP_TRY_TO_1ST;
  387.  cmap_map_to_1st  = DEFAULT_CMAP_MAP_TO_1ST;
  388.  
  389.  anim_flags        = 0;
  390. ANIM_CYCON;
  391.  merged_anim_flags = 0;
  392.  
  393.  if (DEFAULT_IFF_LOOP_OFF  == TRUE) anim_flags |= ANIM_NOLOP;
  394.  if (DEFAULT_CYCLE_ON_FLAG == TRUE) anim_flags |= ANIM_CYCON;
  395.  if (DEFAULT_LACE_FLAG     == TRUE) anim_flags |= ANIM_LACE;
  396.  
  397. /* What rev are we running
  398.  */
  399.  fprintf(stderr,"XAnim Rev %2.2f.%ld  by Mark Podlipec (c) 1990,1991,1992\n",DA_REV,DA_MINOR_REV);
  400.  
  401. /* quick command line check.
  402.  */
  403.  if (argc<2) Usage();
  404.  
  405. /* setup for dying time.
  406.  */
  407.  signal(SIGINT,Hard_Death);
  408.  
  409.  /* PreSet of X11 Display to find out what we're dealing with
  410.   */
  411.  X11_Pre_Setup(argc, argv);
  412.  
  413. /* Parse command line.
  414.  */
  415.  for(i=1;i<argc;i++)
  416.  {
  417.    in = argv[i];
  418.    if ( (in[0]=='-') || (in[0]=='+') )
  419.    {
  420.      int len,opt_on;
  421.  
  422.      if (in[0]=='-') opt_on = FALSE;
  423.      else opt_on = TRUE;
  424.      /* if + turns off then reverse opt_on */
  425.      if (DEFAULT_PLUS_IS_ON == FALSE) opt_on = (opt_on==TRUE)?FALSE:TRUE;
  426.  
  427.      len = strlen(argv[i]);
  428.      j = 1;
  429.      while( (j<len) && (in[j]!=0) )
  430.      {
  431.        switch(in[j])
  432.        {
  433.     int tmp_len;
  434.         case 'C':
  435.           j++;
  436.           switch(in[j])
  437.           {
  438.             case 'l': cmap_luma_sort  = opt_on; j++; break;
  439.             case 't': cmap_try_to_1st = opt_on; j++; break;
  440.             case 'f': cmap_map_to_1st = opt_on; j++; break;
  441.           }
  442.                 break;
  443.         case 'F':
  444.                 dither_flag = opt_on;    j++;    break;
  445.         case 'b':
  446.                 buff_flag = opt_on;    j++;    break;
  447.         case 'c':
  448.                 if (opt_on==TRUE) anim_flags |= ANIM_NOLOP;
  449.                 else anim_flags &= (~ANIM_NOLOP);
  450.                 j++; break;
  451.         case 'd':
  452.                 j++; debug = atoi(&in[j]);
  453.                 if (debug <= 0) debug = 0;
  454.         j += strlen(&in[j]);    break;
  455.         case 'f':
  456.                 j++; fade_time = atoi(&in[j]);
  457.                 if (fade_time <= 0) fade_flag = 0;
  458.                 else fade_flag = 1;
  459.         j += strlen(&in[j]);    break;
  460.         case 'l':
  461.         j++; loopeach_flag = atoi(&in[j]);
  462.                 if (loopeach_flag<=0) loopeach_flag = 1;
  463.         j += strlen(&in[j]);    break;
  464.         case 'i':
  465.                 if (opt_on==TRUE) anim_flags |= ANIM_LACE;
  466.                 else anim_flags &= (~ANIM_LACE);
  467.                 j++;    break;
  468.         case 'j':
  469.                 j++; jiffy_flag = atoi(&in[j]);
  470.                 if (jiffy_flag<=0) jiffy_flag = 1;
  471.         j += strlen(&in[j]);
  472.                 break;
  473.         case 'o':
  474.                 optimize_flag = opt_on;
  475.                 j++;    break;
  476.         case 'p':
  477.                 pixmap_flag = opt_on;    j++;    break;
  478.         case 'r':
  479.                 cycle_on_flag = opt_on;
  480.                 if (opt_on==TRUE)   anim_flags |= ANIM_CYCON;
  481.                 else            anim_flags &= (~ANIM_CYCON);
  482.                 j++;
  483.                 break;
  484.         case 's':
  485.                 noresize_flag = opt_on;    j++;    break;
  486.         case 'u':
  487.                 update_flag = opt_on;    j++;    break;
  488.         case 'v':
  489.                 verbose = opt_on;    j++;    break;
  490.         case '-':
  491.                 opt_on = (DEFAULT_PLUS_IS_ON==TRUE)?FALSE:TRUE; j++;    break;
  492.         case '+':
  493.                 opt_on = (DEFAULT_PLUS_IS_ON==TRUE)?TRUE:FALSE; j++;    break;
  494.         default:
  495.                 Usage();
  496.        } /* end of option switch */
  497.      } /* end of loop through options */
  498.    } /* end of if - */
  499.    else 
  500.    /* If no hyphen in front of argument, assume it's a file.
  501.     */
  502.    {
  503.      action_start = action_cnt;
  504.      filename = argv[i];
  505.  
  506.      if ( (x11_display_type == MONOCHROME) || (pack_flag == TRUE) )
  507.        anm_map_flag = FALSE;
  508.      else
  509.        anm_map_flag = TRUE;
  510.         /* default is FLI  */
  511.      cur_file = Get_Anim_Hdr(cur_file);
  512.      anim_type = Determine_Anim_Type(filename);
  513.      cur_file->anim_type = anim_type;
  514.      if (x11_display_type == MONOCHROME) optimize_flag = FALSE;
  515.      switch(anim_type)
  516.      {
  517.         int action_number,ii;
  518.  
  519.  
  520.         case IFF_ANIM:
  521.                 if (verbose) fprintf(stderr,"Reading IFF File %s\n",filename);
  522.                 merged_anim_flags |= ANIM_IFF;
  523.                 IFF_Read_File(filename,cur_file);
  524.                 if (buff_flag) IFF_Buffer_Action(action_start);
  525.                 break;
  526.         case GIF_ANIM:
  527.                 if (verbose) fprintf(stderr,"Reading GIF File %s\n",filename);
  528.                 GIF_Read_File(filename);
  529.  
  530.                 action_number = action_cnt - action_start;
  531.                 cur_file->frame_lst = 
  532.                       (int *)malloc(sizeof(int) * (action_number+1));
  533.                 if (cur_file->frame_lst == NULL)
  534.                       TheEnd1("GIF_ANIM: couldn't malloc for frame_lst\0");
  535.                 for(ii=0; ii < action_number; ii++)
  536.                             cur_file->frame_lst[ii]=action_start+ii;
  537.                 cur_file->frame_lst[action_number] = -1;
  538.                 cur_file->loop_frame = 0;
  539.                 cur_file->last_frame = action_number-1;
  540.                 break;
  541.         case TXT_ANIM:
  542.                 if (verbose) fprintf(stderr,"Reading TXT File %s\n",filename);
  543.                 TXT_Read_File(filename,cur_file);
  544.                 break;
  545.         case FLI_ANIM:
  546.                 Fli_Read_File(filename,cur_file);
  547.                 break;
  548.         case DL_ANIM:
  549.                 DL_Read_File(filename,cur_file);
  550.                 break;
  551. /* Temporary
  552.         case JPG_ANIM:
  553.                 JFIF_Read_File(filename,cur_file);
  554.  
  555.                 action_number = action_cnt - action_start;
  556.                 cur_file->frame_lst =
  557.                       (int *)malloc(sizeof(int) * (action_number+1));
  558.                 if (cur_file->frame_lst == NULL)
  559.                       TheEnd1("JPG_ANIM: couldn't malloc for frame_lst\0");
  560.                 for(ii=0; ii < action_number; ii++)
  561.                             cur_file->frame_lst[ii]=action_start+ii;
  562.                 cur_file->frame_lst[action_number] = -1;
  563.                 cur_file->loop_frame = 0;
  564.                 cur_file->last_frame = action_number-1;
  565.                 break;
  566. */
  567.         default:
  568.                 fprintf(stderr,"Unknown or unsupported animation type\n");
  569.                 break;
  570.       } 
  571.       /*
  572.        * Setup up anim header.
  573.        */
  574.       cur_file->imagex = imagex;
  575.       cur_file->imagey = imagey;
  576.       cur_file->imagec = imagec;
  577.       cur_file->imaged = imaged;
  578.       cur_file->anim_flags = anim_flags;
  579.       cur_file->loop_num = loopeach_flag;
  580.       merged_anim_flags |= anim_flags;
  581.  
  582.       if (imagex > max_imagex) max_imagex = imagex;
  583.       if (imagey > max_imagey) max_imagey = imagey;
  584.       if (anim_flags & ANIM_LACE)
  585.       {
  586.         if ((imagey/2) > max_disp_y) max_disp_y = imagey/2;
  587.       }
  588.       else
  589.       {
  590.         if ( imagey     > max_disp_y) max_disp_y = imagey;
  591.       }
  592.  
  593.       /*
  594.        * If fade flag is on, basically insert a fade anim.
  595.        */
  596.       if (fade_flag && (x11_cmap_flag == TRUE) )
  597.       {
  598.         int ii;
  599.  
  600.         cur_file = Get_Anim_Hdr(cur_file);
  601.         cur_file->anim_type = FADE_ANIM;
  602.    
  603.         /* Fade to Black action */
  604.         action_start = action_cnt;
  605.         action[action_cnt].type = ACT_FADE;
  606.         action[action_cnt].time = fade_time;
  607.         action[action_cnt].data = 0;
  608.         action_cnt++;
  609.         /* Blank screen so next CMAP doesn't show */
  610.         action[action_cnt].type = ACT_FLI_BLACK;
  611.         action[action_cnt].time = fade_time;
  612.         action[action_cnt].data = 0;
  613.         action_cnt++;
  614.  
  615.  
  616.         /* 
  617.          * Setup frame list to call ACT_FADE sixteen times and FLI_BLACK once.
  618.          */
  619.         cur_file->frame_lst = (int *)malloc(sizeof(int) * (18));
  620.         if (cur_file->frame_lst == NULL)
  621.                   TheEnd1("FADE_ANIM: couldn't malloc for frame_lst\0");
  622.         for(ii=0;ii<16;ii++) cur_file->frame_lst[ii] = action_start;
  623.         cur_file->frame_lst[16] = action_start+1;
  624.         /* Last frame is always -1
  625.          */
  626.         cur_file->frame_lst[17] = -1;
  627.  
  628.         cur_file->imagex = imagex;
  629.         cur_file->imagey = imagey;
  630.         cur_file->imagec = imagec;
  631.         cur_file->imaged = imaged;
  632.         cur_file->anim_flags = anim_flags;
  633.         cur_file->loop_num = 1;
  634.         cur_file->loop_frame = 0;
  635.         cur_file->last_frame = 16;
  636.       } /* end of fade anim insertion */
  637.  
  638.     } /* end of read in file */
  639.  } /* end of loopin through arguments */
  640.  
  641.  /* No anims listed
  642.   */
  643.  if (first_file == 0) Usage();
  644.  
  645.  /* Set up X11 Display
  646.   */
  647.  
  648.  if (noresize_flag==TRUE)
  649.   X11_Setup(max_imagex,max_disp_y,max_imagex,max_disp_y);
  650.  else X11_Setup(max_imagex,max_disp_y,first_file->imagex,
  651.    (first_file->anim_flags & ANIM_LACE)?(first_file->imagey/2):
  652.                     (first_file->imagey)  );
  653.  
  654.  if (x11_display_type == MONOCHROME) optimize_flag = FALSE;
  655.  /* Start off Animation.
  656.   */
  657.  ShowAnimation();
  658.  /* Wait for user input.
  659.   */
  660.  xanim_events();
  661.  
  662.  /* Self-Explanatory
  663.   */
  664.  TheEnd();
  665. }
  666.  
  667. /* Routine to read a long word.
  668.  * yeah, I know macro's are faster.
  669.  */
  670. ULONG GetWord(fp)
  671. FILE *fp;
  672. {
  673.  ULONG ret;
  674.  
  675.  ret =  fgetc(fp);
  676.  ret |= fgetc(fp) << 8;
  677.  ret |= fgetc(fp) << 16;
  678.  ret |= fgetc(fp) << 24;
  679.  return ret;
  680. }
  681.  
  682. /* Routine to read a half word.
  683.  * yeah, I know macro's are faster.
  684.  */
  685. ULONG GetHalfWord(fp)
  686. FILE *fp;
  687. {
  688.  ULONG ret;
  689.  
  690.  ret =  fgetc(fp);
  691.  ret |= fgetc(fp) << 8;
  692.  return ret;
  693. }
  694.  
  695.  
  696. /*
  697.  * ShowAnimation allocates and sets up required image buffers and
  698.  * initializes animation variables.
  699.  * It then kicks off the animation.
  700.  */
  701. void ShowAnimation()
  702. {
  703.   max_image_size = max_imagex * max_imagey;
  704.   im_buff0 = (char *) malloc( max_image_size * x11_bytes_pixel);
  705.   if (im_buff0 == 0) TheEnd1("ShowAnimation: im_buff0 malloc failed");
  706.   if (merged_anim_flags & ANIM_IFF)
  707.   {
  708.     im_buff1 = (char *) malloc( max_image_size * x11_bytes_pixel);
  709.     if (im_buff1 == 0) TheEnd1("ShowAnimation: im_buff1 malloc failed");
  710.   }
  711.  
  712.   if (   (merged_anim_flags & ANIM_HAM) 
  713.       || (merged_anim_flags & ANIM_LACE)
  714.       || (x11_display_type == MONOCHROME)
  715.       || (x11_display_type == TRUE_COLOR) );
  716.   {
  717.      disp_buff = (char *) malloc( max_image_size * x11_bytes_pixel);
  718.      if (disp_buff == 0) TheEnd1("ShowAnimation: disp_buff malloc failed");
  719.   }
  720.  pic = im_buff0;
  721.  
  722.  cur_file = first_file;
  723.  cur_floop = 0;
  724.  cur_frame = -1;  /* since we step first */
  725.  file_is_started = FALSE;
  726.  cycle_wait = 0;
  727.  cycle_cnt = 0;
  728.  
  729.  XtAppAddTimeOut(theContext, 1, ShowAction, NULL);
  730. }
  731.  
  732. /*
  733.  * This is the heart of this program. It does each action and then calls
  734.  * itself with a timeout via the XtAppAddTimeOut call.
  735.  */
  736. void ShowAction(nothing,id)
  737. char *nothing;
  738. XtIntervalId *id;
  739. {
  740.  int screen_updated;
  741.  int t_frame_start,t_frame_end,t_frame_int;
  742.  struct tms tms3;
  743.  
  744.  /* Some actions don't change screen. Useful to know
  745.   */
  746.  screen_updated = FALSE;
  747.  
  748.  /* If color cycling, wait for user go ahead.
  749.   */
  750.  if (cycle_wait && cycle_cnt)
  751.  {
  752.   XtAppAddTimeOut(theContext, 50, ShowAction, NULL);
  753.   return;
  754.  }
  755.  
  756.   switch (anim_status)
  757.   {
  758.     case XA_RUN_NEXT:   
  759.                         Step_Action_Next();
  760.                         break;
  761.     case XA_RUN_PREV:   
  762.                         Step_Frame_Prev();
  763.                         break;
  764.     case XA_STEP_NEXT: 
  765.                         Step_Frame_Next();
  766.                         break;
  767.     case XA_STEP_PREV:
  768.                         Step_Frame_Prev();
  769.                         break;
  770.     case XA_FILE_NEXT:
  771.                         Step_File_Next();
  772.                         anim_status = XA_STEP_NEXT;
  773.                         break;
  774.     case XA_FILE_PREV:
  775.                         Step_File_Prev();
  776.                         anim_status = XA_STEP_PREV;
  777.                         break;
  778.     case XA_UNSTARTED:  
  779.     case XA_STOP_NEXT:  
  780.     case XA_STOP_PREV:  
  781.                         anim_holdoff = FALSE;
  782.                         return;
  783.                         break;
  784.     default:
  785.                         anim_holdoff = FALSE;
  786.                         return;
  787.                         break;
  788.   }
  789.  
  790.   DEBUG_LEVEL1 fprintf(stderr,"frame = %ld\n",cur_frame);
  791.  
  792.  /* 1st throught this particular file.
  793.   * Resize if necessary and init required variables.
  794.   */
  795.  if (file_is_started == FALSE)
  796.  {
  797.   file_is_started = TRUE;
  798.   cycle_wait = 0;
  799.   anim_flags = cur_file->anim_flags;
  800.  
  801.   if (anim_flags & ANIM_CYCON) cycle_on_flag = 1;
  802.   else cycle_on_flag = 0;
  803.  
  804.   /* if interlaced flag then compare half-height images to current settings.
  805.    */
  806.   if (noresize_flag == FALSE)
  807.   {
  808.    if (cur_file->anim_flags & ANIM_LACE)
  809.    {
  810.     if (   (imagex != cur_file->imagex)
  811.         || (disp_y != (cur_file->imagey/2)) ) 
  812.      XResizeWindow(theDisp,mainW,cur_file->imagex,
  813.                                  cur_file->imagey/2);
  814.    }
  815.    else
  816.    {
  817.     if (   (imagex != cur_file->imagex)
  818.        || (disp_y != cur_file->imagey) ) 
  819.      XResizeWindow(theDisp,mainW,cur_file->imagex,
  820.                                  cur_file->imagey);
  821.    }
  822.   }
  823.   else
  824.   {
  825.    if (imagex > cur_file->imagex)
  826.      XClearArea(theDisp,mainW,cur_file->imagex,0, 0,0,FALSE);
  827.    if (  cur_file->anim_flags & ANIM_LACE )
  828.    {
  829.     if (disp_y > (cur_file->imagey>>1) )
  830.       XClearArea(theDisp,mainW,0,(cur_file->imagey/2), 0,0,FALSE);
  831.    }
  832.    else
  833.    {
  834.     if (disp_y > cur_file->imagey )
  835.       XClearArea(theDisp,mainW,0,cur_file->imagey, 0,0,FALSE);
  836.    }
  837.   }
  838.   /* Initialize variables
  839.    */
  840.   imagex = cur_file->imagex;
  841.   imagey = cur_file->imagey;
  842.   imaged = cur_file->imaged;
  843.   imagec = cur_file->imagec;
  844.   image_size = imagex * imagey;
  845.  
  846.   disp_y = (anim_flags & ANIM_LACE)?(imagey>>1):imagey;
  847.  
  848.   X11_Init_Image_Struct(theImage,imagex,imagey,anim_flags);
  849.  
  850.  }
  851.  
  852.  /* OK. A quick sanity check and then we act.
  853.   */
  854.  if (   (cur_file->frame_lst[cur_frame] >= 0)
  855.      && (cur_file->frame_lst[cur_frame] <  action_cnt)  )
  856.  {
  857.     /* initialize act and get the current time.
  858.      */
  859.     act = &action[ cur_file->frame_lst[cur_frame] ];
  860.     t_frame_start = times(&tms3);
  861.     t_frame_int = act->time;
  862.  
  863.  
  864.     /* lesdoit */
  865.     switch(act->type)
  866.     {
  867.        /* 
  868.         * NOP and DELAY don't change anything but can have timing info
  869.         * that might prove useful. ie dramatic pauses :^)
  870.         */
  871.      case ACT_NOP:      
  872.                         DEBUG_LEVEL2 fprintf(stderr,"ACT_NOP:\n");
  873.                         break;
  874.      case ACT_DELAY:    
  875.                         DEBUG_LEVEL2 fprintf(stderr,"ACT_DELAY:\n");
  876.                         break;
  877.        /* 
  878.         * Change Color Map.
  879.         */
  880.      case ACT_CMAP:     
  881.     {
  882.       int j;
  883.       ColorReg *cptr;
  884.       CMAP_HDR *cmap_hdr;
  885.  
  886.       cmap_hdr = (CMAP_HDR *)act->data;
  887.       imagec = cmap_hdr->cmap_size;
  888.       image_map = cptr = (ColorReg *)cmap_hdr->data;
  889.     
  890.       DEBUG_LEVEL2 fprintf(stderr,"CMAP: size=%ld\n",imagec);
  891.       if (x11_cmap_flag == TRUE)
  892.       {
  893.         for(j=0;j<imagec;j++)
  894.         {
  895.           ULONG map;
  896.           map = cptr[j].map;
  897.           defs[j].pixel = map;
  898.           defs[j].red   = cptr[j].red   << 8;
  899.           defs[j].green = cptr[j].green << 8;
  900.           defs[j].blue  = cptr[j].blue  << 8;
  901.           defs[j].flags = DoRed | DoGreen | DoBlue;
  902.           cmap[j].red   = cptr[j].red;
  903.           cmap[j].green = cptr[j].green;
  904.           cmap[j].blue  = cptr[j].blue;
  905.           cmap[j].map   = map;
  906.           DEBUG_LEVEL5 fprintf(stderr,"     <%lx %lx %lx> %ld\n",
  907.           cptr[j].red,cptr[j].green,cptr[j].blue,map);
  908.         }
  909.         XStoreColors(theDisp,theCmap,defs,imagec);
  910.         XFlush(theDisp);
  911.       }
  912.     }
  913.     break;
  914.        /* 
  915.         * Resize Window
  916.         */
  917.      case ACT_SIZE:
  918.         {
  919.           SIZE_HDR *size_hdr;
  920.  
  921.           DEBUG_LEVEL2 fprintf(stderr,"ACT_SIZE:\n");
  922.           size_hdr = (SIZE_HDR *)act->data;
  923.           imagex = size_hdr->imagex;
  924.           imagey = size_hdr->imagey;
  925.       disp_y = (anim_flags & ANIM_LACE)?(imagey>>1):imagey;
  926.           X11_Init_Image_Struct(theImage,imagex,imagey,anim_flags);
  927.         }
  928.         break;
  929.        /* 
  930.         * Lower Color Intensity by 1/16.
  931.         */
  932.      case ACT_FADE:     
  933.                         {
  934.                          int j;
  935.  
  936.                          DEBUG_LEVEL2 fprintf(stderr,"ACT_FADE:\n");
  937.                          if ( (x11_display_type == PSEUDO_COLOR) &&
  938.                               (x11_cmap_flag    == TRUE) )
  939.                          {
  940.                            for(j=0;j<imagec;j++)
  941.                            {
  942.                              if (cmap[j].red   <= 16) cmap[j].red   = 0;
  943.                              else cmap[j].red   -= 16;
  944.                              if (cmap[j].green <= 16) cmap[j].green = 0;
  945.                              else cmap[j].green -= 16;
  946.                              if (cmap[j].blue  <= 16) cmap[j].blue  = 0;
  947.                              else cmap[j].blue  -= 16;
  948.  
  949.                              defs[j].pixel = cmap[j].map;
  950.                              defs[j].red   = cmap[j].red   << 8;
  951.                              defs[j].green = cmap[j].green << 8;
  952.                              defs[j].blue  = cmap[j].blue  << 8;
  953.                              defs[j].flags = DoRed | DoGreen | DoBlue;
  954.                            }
  955.                            XStoreColors(theDisp,theCmap,defs,imagec);
  956.                            XFlush(theDisp);
  957.                          }
  958.                         }
  959.                         screen_updated = TRUE;
  960.                         break;
  961.        /* 
  962.         * A IMAGE display only part of an IMAGE.
  963.         */
  964.      case ACT_IMAGE:   
  965.     {
  966.       ACT_IMAGE_HDR *act_im_hdr;
  967.  
  968.       DEBUG_LEVEL2 fprintf(stderr,"ACT_IMAGE:\n");
  969.       act_im_hdr = (ACT_IMAGE_HDR *)(act->data);
  970.  
  971.       XPutImage(theDisp,mainW,theGC,act_im_hdr->image, 0, 0,
  972.         act_im_hdr->xpos,  act_im_hdr->ypos,
  973.         act_im_hdr->xsize, act_im_hdr->ysize  );
  974.       XFlush(theDisp);
  975.       cycle_wait = 1;
  976.     }
  977.     screen_updated = TRUE;
  978.     break;
  979.  
  980.        /* 
  981.         * A CLIP displays only part of an IMAGE with a clip_mask.
  982.         */
  983.      case ACT_CLIP:     
  984.     {
  985.       Pixmap pix_map;
  986.       ACT_CLIP_HDR *act_cp_hdr;
  987.  
  988.       DEBUG_LEVEL2 fprintf(stderr,"ACT_CLIP:\n");
  989.       act_cp_hdr = (ACT_CLIP_HDR *)(act->data);
  990.  
  991.  
  992.           pix_map = XCreatePixmapFromBitmapData(theDisp,mainW,
  993.         act_cp_hdr->clip_ptr,
  994.         act_cp_hdr->xsize,act_cp_hdr->ysize,
  995.         0x01,0x00,1);
  996.           XSetClipMask(theDisp,theGC,pix_map);
  997.           XSetClipOrigin(theDisp,theGC,act_cp_hdr->xpos,  act_cp_hdr->ypos);
  998.           XPutImage(theDisp,mainW,theGC,act_cp_hdr->image, 0, 0,
  999.         act_cp_hdr->xpos,  act_cp_hdr->ypos,
  1000.         act_cp_hdr->xsize, act_cp_hdr->ysize  );
  1001.           XSetClipMask(theDisp,theGC,None);
  1002.           XFreePixmap(theDisp,pix_map);
  1003.  
  1004.       XFlush(theDisp);
  1005.       cycle_wait = 1;
  1006.     }
  1007.     screen_updated = TRUE;
  1008.     break;
  1009.  
  1010.        /* 
  1011.         * A PIXMAP 
  1012.         */
  1013.      case ACT_PIXMAP:   
  1014.     {
  1015.       ACT_PIXMAP_HDR *act_pm_hdr;
  1016.  
  1017.       DEBUG_LEVEL2 fprintf(stderr,"ACT_PIXMAP:\n");
  1018.       act_pm_hdr = (ACT_PIXMAP_HDR *)(act->data);
  1019.  
  1020.       XCopyArea(theDisp,act_pm_hdr->pixmap,mainW,theGC, 0, 0, 
  1021.         act_pm_hdr->xsize, act_pm_hdr->ysize,
  1022.         act_pm_hdr->xpos,  act_pm_hdr->ypos   );
  1023.       XSync(theDisp,False);
  1024.       cycle_wait = 1;
  1025.     }
  1026.     screen_updated = TRUE;
  1027.     break;
  1028.        /* 
  1029.         * Act upon IFF Color Cycling chunk.
  1030.         *   currently we don't color cycling during animations. will be fixed.
  1031.         */
  1032.      case ACT_IFF_CRNG:
  1033.     {
  1034.       CRNG_HDR *crng;
  1035.  
  1036.       DEBUG_LEVEL2 fprintf(stderr,"ACT_CRNG:\n");
  1037.       if (   (x11_display_type == PSEUDO_COLOR)
  1038.           && (x11_cmap_flag    == TRUE) )
  1039.       {
  1040.         crng = (CRNG_HDR *)act->data;
  1041.         if (   (crng->active & CRNG_ACTIVE)
  1042.             && (crng->low < crng->high)
  1043.             && (crng->rate != 0)
  1044.             && (anim_flags & ANIM_CYCLE) 
  1045.             && (cycle_on_flag)        )
  1046.         {
  1047.           cycle_cnt++;
  1048.           XtAppAddTimeOut(theContext,(int)(CRNG_INTERVAL/(crng->rate)),
  1049.             Cycle_It, crng);
  1050.         }
  1051.       }
  1052.  
  1053.     }
  1054.     break;
  1055.  
  1056.        /* 
  1057.         *  FLI BRUN chunk
  1058.         *  FLI LC chunk
  1059.         *  FLI LC7 chunk
  1060.         *  FLI COPY chunk
  1061.         *  FLI BLACK chunk
  1062.         */
  1063.      case ACT_FLI_BRUN:   
  1064.      case ACT_FLI_LC:   
  1065.      case ACT_FLI_LC7:
  1066.      case ACT_FLI_COPY:
  1067.      case ACT_FLI_BLACK:        
  1068.     {
  1069.       ULONG xpos,ypos,xsize,ysize;
  1070.  
  1071.       switch(act->type)
  1072.       {
  1073.         case ACT_FLI_BRUN: 
  1074.         DEBUG_LEVEL2 fprintf(stderr,"ACT_FLI_BRUN:\n");
  1075.         Decode_Fli_BRUN(image_map, act->data,pic,TRUE);
  1076.         xpos = ypos = 0; xsize = imagex;  ysize = imagey;
  1077.         break;
  1078.         case ACT_FLI_LC:
  1079.         DEBUG_LEVEL2 fprintf(stderr,"ACT_FLI_LC:\n");
  1080.         Decode_Fli_LC( image_map, act->data, pic, 
  1081.             &xpos,&ypos,&xsize,&ysize,TRUE);
  1082.         break;
  1083.         case ACT_FLI_LC7:
  1084.         DEBUG_LEVEL2 fprintf(stderr,"ACT_FLI_LC7:\n");
  1085.         Decode_Fli_LC7( image_map, act->data, pic, 
  1086.             &xpos,&ypos,&xsize,&ysize,TRUE);
  1087.         break;
  1088.         case ACT_FLI_COPY:
  1089.         DEBUG_LEVEL2 fprintf(stderr,"ACT_FLI_COPY:\n");
  1090.         if (x11_display_type == TRUE_COLOR)
  1091.         {
  1092.           memcpy(disp_buff,(char *)act->data,image_size);
  1093.           UTIL_Sub_Mapped_To_True(pic,disp_buff,image_map,
  1094.                     0,0,imagex,imagey,imagex);
  1095.         }
  1096.         else memcpy(pic,(char *)act->data,image_size);
  1097.         xpos = ypos = 0; xsize = imagex;  ysize = imagey;
  1098.         break;
  1099.         case ACT_FLI_BLACK:        
  1100.         DEBUG_LEVEL2 fprintf(stderr,"ACT_FLI_BLACK:\n");
  1101.         memset(pic,0x00,image_size * x11_bytes_pixel);
  1102.         xpos = ypos = 0; xsize = imagex;  ysize = imagey;
  1103.         break;
  1104.       }
  1105.  
  1106.       if (x11_display_type == MONOCHROME)
  1107.       {
  1108.         ULONG line_size;
  1109.         line_size = X11_Get_Line_Size(imagex);
  1110.         UTIL_Mapped_To_Bitmap(disp_buff,pic,image_map,imagec,
  1111.             imagex,imagey,line_size);
  1112.         theImage->data = disp_buff;
  1113.       }
  1114.       else theImage->data = pic;
  1115.  
  1116.       X11_Init_Image_Struct(theImage,imagex,imagey,anim_flags);
  1117.           if (anim_flags & ANIM_LACE) 
  1118.       { 
  1119.         if (!(ypos & 0x01)) ysize++;
  1120.         ypos++; ypos >>= 1;
  1121.         ysize >>= 1;
  1122.       }
  1123.       XPutImage(theDisp,mainW,theGC,theImage,
  1124.         xpos,ypos,xpos,ypos,xsize,ysize );
  1125.       XSync(theDisp,False);
  1126.     }
  1127.     screen_updated = TRUE;
  1128.     break;
  1129.  
  1130.        /* 
  1131.         *  FLI_COLOR not supported. Actually it become a CMAP when read in.
  1132.         */
  1133.      case ACT_FLI_COLOR:        
  1134.                         fprintf(stderr,"fli_color not supported\n");
  1135.                         break;
  1136.  
  1137.        /* 
  1138.         *  Display IFF body. Note that both buffers are set to this body.
  1139.         *  this is necessary since next delta works on 2nd buffer.
  1140.         * 
  1141.         *  Handle IFF anim op 3 and op l(small L) compressed actions.
  1142.         */
  1143.      case ACT_IFF_BODY:
  1144.      case ACT_IFF_DLTAl:
  1145.      case ACT_IFF_DLTA3:
  1146.     {
  1147.         int src_x,src_y,im_x,im_y;
  1148.         switch(act->type)
  1149.         {
  1150.          case ACT_IFF_DLTAl:
  1151.             DEBUG_LEVEL2 fprintf(stderr,"ACT_IFF_DLTAl:\n");
  1152.             IFF_Deltal(im_buff0, (short *)act->data, 1);
  1153.             break;
  1154.          case ACT_IFF_DLTA3:
  1155.             DEBUG_LEVEL2 fprintf(stderr,"ACT_IFF_DLTA3:\n");
  1156.             IFF_Delta3(im_buff0, act->data);
  1157.             break;
  1158.          case ACT_IFF_BODY:
  1159.             DEBUG_LEVEL2 fprintf(stderr,"ACT_IFF_BODY:\n");
  1160.             memcpy(im_buff0,(char *)act->data,image_size);
  1161.             memcpy(im_buff1,(char *)act->data,image_size);
  1162.             IFF_Init_DLTA_HDR(imagex,imagey);
  1163.             break;
  1164.         }
  1165.         IFF_Image_To_Displayable( &(theImage->data), disp_buff, im_buff0,
  1166.                 image_map, ham_map, imagec,
  1167.                 &src_x, &src_y, &im_x, &im_y,
  1168.         imagex, imagey, 0, 0, imagex, imagey, anim_flags);
  1169.         X11_Init_Image_Struct(theImage,im_x,im_y,anim_flags);
  1170.         XPutImage(theDisp,mainW,theGC,theImage,0,0,0,0,imagex,disp_y);
  1171.         XSync(theDisp,False);
  1172.         screen_updated = TRUE;
  1173.         if (act->type == ACT_IFF_BODY) cycle_wait = 1;
  1174.         else { pic = im_buff0; im_buff0 = im_buff1; im_buff1 = pic; }
  1175.     }
  1176.         break;
  1177.  
  1178.  
  1179.        /* 
  1180.         *  Handle IFF anim op 5 and opt J compressed actions. 
  1181.         */
  1182.      case ACT_IFF_DLTAJ:
  1183.      case ACT_IFF_DLTA5:
  1184.         {
  1185.           int minx,miny,maxx,maxy,pic_x,pic_y,src_x,src_y,im_x,im_y;
  1186.  
  1187.           if (act->type == ACT_IFF_DLTAJ)
  1188.           {
  1189.             DEBUG_LEVEL2 fprintf(stderr,"ACT_IFF_DLTAJ:\n");
  1190.             IFF_DeltaJ(im_buff0, act->data, &minx, &miny, &maxx, &maxy);
  1191.           }
  1192.           else if (act->type == ACT_IFF_DLTA5)
  1193.           {
  1194.             DEBUG_LEVEL2 fprintf(stderr,"ACT_IFF_DLTA5:\n");
  1195.             IFF_Delta5(im_buff0, act->data, &minx, &miny, &maxx, &maxy);
  1196.           }
  1197.           else break;
  1198.  
  1199.           if ( (anim_status != XA_RUN_NEXT) && (anim_status != XA_STEP_NEXT) )
  1200.           {
  1201.             minx = miny = 0; maxx = imagex; maxy = imagey;
  1202.           }
  1203.           IFF_Update_DLTA_HDR(&minx,&miny,&maxx,&maxy);
  1204.           pic_x = maxx - minx; pic_y = maxy - miny;
  1205.           IFF_Image_To_Displayable( &(theImage->data), disp_buff, im_buff0,
  1206.                 image_map, ham_map, imagec,
  1207.                 &src_x, &src_y, &im_x, &im_y, 
  1208.                 pic_x, pic_y, minx, miny, imagex, imagey, anim_flags);
  1209.  
  1210.           X11_Init_Image_Struct(theImage,im_x,im_y,anim_flags);
  1211. DEBUG_LEVEL1 fprintf(stderr,"src<%ld %ld> min<%ld %ld> pic<%ld %ld> im<%ld %ld>\n",
  1212.     src_x, src_y, minx,  miny, pic_x, pic_y,im_x,im_y);
  1213.  
  1214.           if (anim_flags & ANIM_LACE) 
  1215.       { 
  1216.         if ( (src_y==0) && (miny & 0x01) ) src_x += im_x;
  1217.         else pic_y++;
  1218.         pic_y >>= 1;
  1219.         if (src_y != 0) src_y++;
  1220.         src_y >>= 1;
  1221.         miny++; miny >>= 1;
  1222.       }
  1223.  
  1224. DEBUG_LEVEL1 fprintf(stderr,"src<%ld %ld> min<%ld %ld> pic<%ld %ld> im<%ld %ld>\n\n",
  1225.     src_x, src_y, minx,  miny, pic_x, pic_y,im_x,im_y);
  1226.           XPutImage(theDisp,mainW,theGC,theImage,
  1227.                         src_x, src_y, minx,  miny, pic_x, pic_y);
  1228.           XSync(theDisp,False);
  1229.           pic = im_buff0; im_buff0 = im_buff1; im_buff1 = pic;
  1230.         }
  1231.         screen_updated = TRUE;
  1232.         break;
  1233.  
  1234.        /* 
  1235.         *  Update ham_map if it changes during an animation. ham_map is
  1236.         *  needed in order to convert HAM images into displayable images.
  1237.         */
  1238.      case ACT_IFF_HMAP: 
  1239.         {
  1240.           ColorReg *hptr;
  1241.           int i;
  1242.  
  1243.           DEBUG_LEVEL2 fprintf(stderr,"ACT_IFF_HMAP:\n");
  1244.           hptr = (ColorReg *)act->data;
  1245.           for(i=0;i<HMAP_SIZE;i++)
  1246.           {
  1247.             ham_map[i].red   = hptr[i].red;
  1248.             ham_map[i].green = hptr[i].green;
  1249.             ham_map[i].blue  = hptr[i].blue;
  1250.           }
  1251.         }
  1252.         break;
  1253.      default:           
  1254.                         fprintf(stderr,"Unknown not supported %lx\n",act->type);
  1255.     } /* end of switch of action type */
  1256.  } /* end of action valid */
  1257.  
  1258. /* Move on if we're running. If we're in single step mode and the update_flag
  1259.  * is set, we move on until the screen has been updated. 
  1260.  */
  1261.  
  1262.  if ( (anim_status == XA_STEP_NEXT) || (anim_status == XA_STEP_PREV) )
  1263.  {
  1264.    if ( (update_flag == FALSE) || (screen_updated == TRUE) )
  1265.    {
  1266.      if (anim_status == XA_STEP_NEXT)
  1267.      {
  1268.        anim_status = XA_STOP_NEXT;
  1269.        anim_holdoff = FALSE;
  1270.        return;
  1271.      }
  1272.      else if (anim_status == XA_STEP_PREV)
  1273.           {
  1274.             anim_status = XA_STOP_PREV;
  1275.             anim_holdoff = FALSE;
  1276.             return;
  1277.           }
  1278.    }
  1279.  }
  1280.  
  1281.  
  1282.   /* Harry, what time is it?
  1283.    */
  1284.  t_frame_end = times(&tms3) - t_frame_start;
  1285.  t_frame_end *= 1000/HZ;  /* convert to milliseconds */
  1286.  
  1287.   /* how much time left 
  1288.    */
  1289.  t_frame_end = t_frame_int - t_frame_end;  
  1290.   /* default to 1 ms, other wise 100 clk_tcks gives 10ms per tick.
  1291.    * NOTE: change all timing to milliseconds, not ticks.
  1292.    */
  1293.  if (t_frame_end <=0 ) t_frame_end = 1; 
  1294.  if ( (anim_status != XA_STOP_NEXT) || (anim_status != XA_STOP_PREV) ) 
  1295.    XtAppAddTimeOut(theContext, t_frame_end, ShowAction, NULL);
  1296.  else anim_holdoff = FALSE;
  1297. }
  1298.  
  1299. /*
  1300.  *
  1301.  */
  1302. void
  1303. Step_Action_Next()
  1304. {
  1305.  /* Move to next frame
  1306.   */
  1307.  cur_frame++;
  1308.  
  1309.  /* Are we at the end of an anim?
  1310.   */
  1311.  if (   (cur_file->frame_lst[cur_frame] < 0)
  1312.      || (cur_file->frame_lst[cur_frame] >= action_cnt) )
  1313.  {
  1314.    cur_frame = cur_file->loop_frame;
  1315.  
  1316.    cur_floop++;
  1317.    DEBUG_LEVEL1 fprintf(stderr,"  loop = %ld\n",cur_floop);
  1318.  
  1319.    /* Done looping animation. Move on to next file if present
  1320.     */
  1321.    if (cur_floop >= cur_file->loop_num)
  1322.    {
  1323.      cur_floop = 0;             /* Reset Loop Count */
  1324.  
  1325.      /* This is a special case check.
  1326.       * If more that one file, reset file_is_started, otherwise
  1327.       * if we're only displaying 1 animation jump to the loop_frame
  1328.       * which has already been set up above.
  1329.       */
  1330.      if (first_file->next_file != first_file )
  1331.      {
  1332.        file_is_started = FALSE;
  1333.        cur_frame = 0;
  1334.      } /* end of move on to next file/anim */
  1335.  
  1336.      cur_file = cur_file->next_file;
  1337.  
  1338.      DEBUG_LEVEL1
  1339.        fprintf(stderr,"  file = %ld\n",cur_file->file_num);
  1340.    } /* end done looping file */
  1341.  } /* end done with frames in file */
  1342. }
  1343.  
  1344. /*
  1345.  *
  1346.  */
  1347. void
  1348. Step_Frame_Next()
  1349. {
  1350.  /* Move to next frame
  1351.   */
  1352.  cur_frame++;
  1353.  
  1354.  /* Are we at the end of an anim?
  1355.   */
  1356.  if (   (cur_file->frame_lst[cur_frame] < 0)
  1357.      || (cur_file->frame_lst[cur_frame] >= action_cnt) )
  1358.  {
  1359.    cur_frame = cur_file->loop_frame;
  1360.  }
  1361. }
  1362.  
  1363. /*
  1364.  *
  1365.  */
  1366. void
  1367. Step_Frame_Prev()
  1368. {
  1369.  /* Move to next frame
  1370.   */
  1371.  cur_frame--;
  1372.  
  1373.  /* Are we at the beginning of an anim?
  1374.   */
  1375.  if (   (cur_file->frame_lst[cur_frame] < 0)
  1376.      || (cur_file->frame_lst[cur_frame] >= action_cnt) 
  1377.      || (cur_frame < cur_file->loop_frame)
  1378.      || (cur_frame < 0)
  1379.     )
  1380.  {
  1381.    cur_frame = cur_file->last_frame;
  1382.  }
  1383. }
  1384.  
  1385. /*
  1386.  *
  1387.  */
  1388. void
  1389. Step_File_Next()
  1390. {
  1391.   file_is_started = FALSE;
  1392.   cur_frame = 0;
  1393.   cur_floop = 0; /* used if things start up again */
  1394.   cur_file = cur_file->next_file;
  1395.  
  1396.   if (debug) fprintf(stderr,"  file = %ld\n",cur_file);
  1397. }
  1398.  
  1399. /*
  1400.  *
  1401.  */
  1402. void
  1403. Step_File_Prev()
  1404. {
  1405.   file_is_started = FALSE;
  1406.   cur_frame = 0;
  1407.   cur_floop = 0; /* used if things start up again */
  1408.   cur_file = cur_file->prev_file;
  1409.  
  1410.   if (debug) fprintf(stderr,"  file = %ld\n",cur_file);
  1411. }
  1412.  
  1413.  
  1414. /*
  1415.  * Simple routine to find out the file type. Defaults to FLI.
  1416.  */
  1417. int Determine_Anim_Type(filename)
  1418. char *filename;
  1419. {
  1420.  if ( Is_IFF_File(filename) ) return(IFF_ANIM); 
  1421.  if ( Is_GIF_File(filename) ) return(GIF_ANIM); 
  1422.  if ( Is_TXT_File(filename) ) return(TXT_ANIM); 
  1423.  if ( Is_FLI_File(filename) ) return(FLI_ANIM); 
  1424.  if ( Is_DL_File(filename)  ) return(DL_ANIM);
  1425. /* Temporary
  1426.  if ( Is_JFIF_File(filename)  ) return(JPG_ANIM);
  1427. */
  1428.  return(UNKNOWN_ANIM);
  1429. }
  1430.  
  1431. void Cycle_It(crng, id)
  1432. CRNG_HDR   *crng;
  1433. XtIntervalId *id;
  1434. {
  1435.   int             i,clow,chi;
  1436.   XColor          tmp_def;
  1437.  
  1438.   if ((anim_flags & ANIM_CYCLE) && cycle_on_flag) 
  1439.    XtAppAddTimeOut(theContext,(int)(CRNG_INTERVAL/(crng->rate)),Cycle_It, crng);
  1440.   else cycle_cnt--;
  1441.  
  1442.   clow = crng->low;
  1443.   chi = crng->high;
  1444.  
  1445.   if (crng->active & CRNG_REVERSE) 
  1446.   {
  1447.     tmp_def = defs[clow];
  1448.     for (i = clow; i < chi; i++) defs[i] = defs[i + 1];
  1449.     defs[chi] = tmp_def;
  1450.   } 
  1451.   else 
  1452.   {
  1453.     tmp_def = defs[chi];
  1454.     for (i = chi; i > clow; i--) defs[i] = defs[i - 1];
  1455.     defs[clow] = tmp_def;
  1456.   }
  1457.  
  1458.   /* POD this is wrong. pixel should be i + (x11_cmap_size - imagec)
  1459.    * but should be worked into crng chunk up front
  1460.    */
  1461.   for (i = clow; i <= chi; i++) defs[i].pixel = x11_cmap_size - imagec + i;
  1462.  
  1463.   if ( (x11_display_type == PSEUDO_COLOR) &&
  1464.        (x11_cmap_flag    == TRUE) )
  1465.   {
  1466.     XStoreColors(theDisp,theCmap,&defs[clow],(chi - clow + 1) );
  1467.     XSync(theDisp,False);
  1468.   }
  1469. }
  1470.  
  1471. void
  1472. Free_Actions()
  1473. {
  1474.   ACTION *act;
  1475.   ULONG i;
  1476.  
  1477.   if (action_cnt <= 0) return;
  1478.  
  1479.   for(i=0;i<action_cnt;i++)
  1480.   {
  1481.     act = &action[i];
  1482.  
  1483.     switch(act->type)
  1484.     {
  1485.       case ACT_IMAGE:
  1486.         {
  1487.           ACT_IMAGE_HDR *act_im_hdr;
  1488.           act_im_hdr = (ACT_IMAGE_HDR *)(act->data);
  1489.           XDestroyImage(act_im_hdr->image);
  1490.           free(act->data);
  1491.         }
  1492.         break;
  1493.       case ACT_CLIP:
  1494.         {
  1495.           ACT_CLIP_HDR *act_cp_hdr;
  1496.           act_cp_hdr = (ACT_CLIP_HDR *)(act->data);
  1497.           free(act_cp_hdr->clip_ptr);
  1498.           XDestroyImage(act_cp_hdr->image);
  1499.           free(act->data);
  1500.         }
  1501.         break;
  1502.       case ACT_PIXMAP:
  1503.         {
  1504.           ACT_PIXMAP_HDR *act_pm_hdr;
  1505.           act_pm_hdr = (ACT_PIXMAP_HDR *)(act->data);
  1506.           XFreePixmap(theDisp,act_pm_hdr->pixmap);
  1507.           free(act->data);
  1508.           DEBUG_LEVEL1 fprintf(stderr,"  freed ACT_PIXMAP\n");
  1509.         }
  1510.         break;
  1511.       default:
  1512.         if (act->data != 0) free(act->data);
  1513.         break;
  1514.     }
  1515.   }
  1516. }
  1517.  
  1518. ANIM_HDR *Get_Anim_Hdr(file_hdr)
  1519. ANIM_HDR *file_hdr;
  1520. {
  1521.   ANIM_HDR *temp_hdr;
  1522.   static int file_num;
  1523.  
  1524.   temp_hdr = (ANIM_HDR *)malloc( sizeof(ANIM_HDR) );
  1525.   if (temp_hdr == 0) TheEnd1("Get_Anim_Hdr: malloc failed\n");
  1526.  
  1527.   if (first_file == 0) first_file = temp_hdr;
  1528.   if (file_hdr == 0)
  1529.   {
  1530.     file_num = 0;
  1531.     temp_hdr->next_file = temp_hdr;
  1532.     temp_hdr->prev_file = temp_hdr;
  1533.   }
  1534.   else
  1535.   {
  1536.     temp_hdr->prev_file = file_hdr;
  1537.     temp_hdr->next_file = file_hdr->next_file;
  1538.     file_hdr->next_file = temp_hdr;
  1539.   }
  1540.  
  1541.   temp_hdr->anim_type = 0;
  1542.   temp_hdr->imagex = 0;
  1543.   temp_hdr->imagey = 0;
  1544.   temp_hdr->imagec = 0;
  1545.   temp_hdr->imaged = 0;
  1546.   temp_hdr->imaged = 0;
  1547.   temp_hdr->anim_flags = 0;
  1548.   temp_hdr->loop_num   = 0;
  1549.   temp_hdr->loop_frame = 0;
  1550.   temp_hdr->frame_lst  = 0;
  1551.   temp_hdr->file_num = file_num;
  1552.   file_num++;
  1553.  
  1554.   return(temp_hdr);
  1555. }
  1556.   
  1557.